package org.test4j.mock.processor.filer.file;

import g_asm.org.objectweb.asm.ClassVisitor;
import g_asm.org.objectweb.asm.Label;
import g_asm.org.objectweb.asm.MethodVisitor;
import g_asm.org.objectweb.asm.Type;
import org.test4j.mock.faking.meta.MethodId;

import java.lang.reflect.Modifier;

import static org.test4j.mock.faking.util.AsmConstant.api_code;
import static org.test4j.mock.faking.util.TypeUtility.isSynthetic;

/**
 * 解析class文件method
 *
 * @author darui.wu
 */
public class ParseMethodVisitor extends ClassVisitor {
    private MockClassFiler filer;

    public ParseMethodVisitor(MockClassFiler filer) {
        super(api_code);
        this.filer = filer;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        if (isSynthetic(access)) {
            return super.visitMethod(access, name, descriptor, signature, exceptions);
        }
        final MethodId methodId = filer.addMethodId(access, name, descriptor);
        boolean isStatic = Modifier.isStatic(access);
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (methodId == null) {
            return mv;
        }
        int count = Type.getArgumentTypes(descriptor).length;
        return new MethodVisitor(api_code, mv) {
            /**
             * 如果是静态方法，第一个参数就是方法参数，非静态方法，则第一个参数是 this ,然后才是方法的参数
             */
            @Override
            public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
                int pIndex = isStatic ? index : index - 1;
                if (pIndex >= 0 && pIndex < count) {
                    methodId.addParaNameType(pIndex, name, desc);
                }
                super.visitLocalVariable(name, desc, signature, start, end, index);
            }
        };
    }
}